// 比较两个数组是否相等（用于比较字母频率）
function isTwoArrayEqual(arr1, arr2) {
    for (let i = 0; i < arr1.length; i++) {
        if (arr2[i] !== arr1[i]) {
            return false; // 如果某一位频率不同，就不是异位词
        }
    }
    return true; // 所有频率相等，说明是异位词
}

/**
 * @param {string} s - 主字符串，在其中查找异位词
 * @param {string} p - 模式字符串，查找其所有异位词在s中的起始索引
 * @return {number[]} - 返回所有匹配的起始索引组成的数组
 */
var findAnagrams = function(s, p) {
    let sLength = s.length; // 主字符串长度
    let pLength = p.length; // 模式字符串长度

    // sArr 和 pArr 用于记录每个字母（a-z）的出现频率
    let sArr = new Array(26).fill(0); // 主字符串中滑动窗口的频率表
    let pArr = new Array(26).fill(0); // 模式字符串的频率表

    // 初始化模式字符串的频率表
    for (let i = 0; i < pLength; i++) {
        let index = p.charCodeAt(i) - 97; // 'a'的ASCII码是97，所以减去97后得到0~25范围
        pArr[index]++;
    }

    let res = []; // 结果数组，存放所有匹配异位词的起始索引

    // 遍历主字符串，用滑动窗口维护当前窗口内的频率表
    for (let i = 0; i < sLength; i++) {
        // 如果当前索引小于p的长度，说明窗口还没满，直接添加
        if (i < pLength) {
            sArr[s.charCodeAt(i) - 97]++;
        } else {
            // 窗口向右滑动一格：
            // 1. 新增当前字符
            sArr[s.charCodeAt(i) - 97]++;
            // 2. 移除窗口左侧的字符
            let leftCharIndex = s.charCodeAt(i - pLength) - 97;
            if (sArr[leftCharIndex] === 0) {
                sArr[leftCharIndex] = 0; // 避免出现负数
            } else {
                sArr[leftCharIndex]--;
            }
        }

        // 如果当前窗口大小等于p的长度，检查是否是异位词
        if (i >= pLength - 1) {
            if (isTwoArrayEqual(pArr, sArr)) {
                res.push(i - pLength + 1); // 添加异位词起始索引
            }
        }
    }

    return res; // 返回所有匹配位置
}

// 测试样例
// 输入: s = "cbaebabacd", p = "abc"
// 输出: [0,6] （"cba"和"bac"是"abc"的异位词）
let s = "cbaebabacd", p = "abc";
console.log(findAnagrams(s, p));
